package com.huiquan.section.service;

import com.huiquan.analysis.domain.User;
import com.huiquan.foundation.constant.BusinessContants;
import com.huiquan.framework.base.BaseService;
import com.huiquan.framework.base.ReturnCode;
import com.huiquan.framework.base.ReturnData;
import com.huiquan.framework.dao.StaticDataDao;
import com.huiquan.framework.domain.StaticData;
import com.huiquan.framework.utils.GetListUtil;
import com.huiquan.framework.utils.RespHeaderUtil;
import com.huiquan.framework.utils.ReturnUtil;
import com.huiquan.section.dao.SectionDao;
import com.huiquan.section.dao.SectionImageDao;
import com.huiquan.section.dao.SectionSynonymyDao;
import com.huiquan.section.domain.Section;
import com.huiquan.section.domain.SectionImage;
import com.huiquan.section.domain.SectionSynonymy;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.*;

@Service
public class SectionSynonymyService extends BaseService {

    @Autowired
    private SectionSynonymyDao sectionSynonymyDao;
    @Autowired
    private SectionImageDao sectionImageDao;
    @Autowired
    private SectionDao sectionDao;
    @Autowired
    private StaticDataDao staticDataDao;

    public ModelAndView list(String startStr, String nameKey, String exactSearchFlag, String countPerPageStr, String section) {

        Map<String, Object> param = new HashMap<>();
        if (nameKey != null && !nameKey.isEmpty()) {
            if (exactSearchFlag != null && exactSearchFlag.equals("1")) {
                param.put("name", nameKey);
            } else {
                param.put("name", "%" + nameKey + "%");
            }
        }
        if (section != null && !section.isEmpty()) {
            if (exactSearchFlag != null && exactSearchFlag.equals("1")) {
                param.put("sectionId", section);
            } else {
                param.put("sectionId", "%" + section + "%");
            }
        }
        int totalSize = sectionSynonymyDao.retrieveSize(param);

        Map<String, Integer> pageNo;
        if (countPerPageStr != null && !countPerPageStr.isEmpty()) {
            int countPerPage = Integer.parseInt(countPerPageStr);
            pageNo = GetListUtil.getPageNoParam(totalSize, startStr, countPerPage);
            param.put("countPerPage", countPerPage);
        } else {
            pageNo = GetListUtil.getPageNoParam(totalSize, startStr);
        }
        int endPage = pageNo.get("endPage");
        int start = pageNo.get("start");
        int startIndex = pageNo.get("startIndex");

        List<SectionSynonymy> list = new ArrayList<>();

        if (startIndex < totalSize) {
            param.put("startIndex", startIndex);
            list = sectionSynonymyDao.retrievesList(param);
        }

        Map<String, String> showSearch = new LinkedHashMap<>();
        showSearch.put("nameKey", "原始科室");
        showSearch.put("section", "科室名称");

        Map<String, Object> map = GetListUtil.getReturnMap2(totalSize, start, startIndex, endPage, list, null);
        map.put("showSearch", showSearch);
        map.put("ageArray", BusinessContants.ageArray);
        // 查询是否含有新增了同义词但没有新增其他的科室图片之类的
        List<StaticData> sds = staticDataDao.retrieveByCode("SECTION_ADD_WARN");
        if (sds.size() > 0) {
            map.put("warn", "1");
            map.put("warnList", sds);
        }
        return new ModelAndView("section/index", map);
    }

    public ModelAndView edit(String id) {
        Map<String, Object> map = new HashMap<>();
        if (StringUtils.isNotBlank(id)) {
            SectionSynonymy value = sectionSynonymyDao.retrieveObjectById(Long.parseLong(id));
            if (value != null) {
                map.put("departmentName", value.getDepartmentName());
                map.put("sectionName", value.getSectionId());
                map.put("id", value.getId());
                map.put("disable", value.getDisable());
            }

        }
        return new ModelAndView("section/section_synonymy_edit", map);
    }

    public void export(HttpServletResponse resp) throws Exception {
        Map<String, Object> param = new HashMap<>();
        param.put("all", "1");
        // 获取已校验code列表
        List<SectionSynonymy> sectionList = sectionSynonymyDao.retrievesList(param);

        // 设置respons的头信息
        RespHeaderUtil.setXlsxResp(resp, "科室同义词");

        Workbook workbook = new XSSFWorkbook(); // 创建文档

        Sheet sheet = workbook.createSheet("科室同义词"); // 创建Sheet
        int i = 0;
        // 循环写入数据
        for (SectionSynonymy section : sectionList) {

            Row row = sheet.createRow(i);

            // 如果是小词同义词中有标准词的，则需要将标准词放在每行的第一格；如果标准词不存在则空,英文标准词同样操作
            Cell cell = row.createCell(0);
            cell.setCellValue(section.getDepartmentName());

            cell = row.createCell(1);
            cell.setCellValue(section.getSectionId());

            cell = row.createCell(2);
            cell.setCellValue(section.getDisable());
            i++;
        }

        OutputStream os = resp.getOutputStream();
        workbook.write(os);

        os.close();
        workbook.close();
    }

    private String getCellNum(Row row, int num) {
        Cell cell = row.getCell(num);
        String index = "";
        if (cell != null) {
            cell.setCellType(Cell.CELL_TYPE_STRING);
            index = cell.getStringCellValue().trim();
        }
        return index;
    }

    /**
     * 批量导入
     */
    public ReturnData insertBatch(User user, MultipartFile file) throws IOException {
        if (file != null) {
            List<SectionSynonymy> addlist = new ArrayList<>();
            List<Section> sts = sectionDao.retrieveList();
            Map<String, Long> ksNameAndSectionId = new HashMap<>();
            List<SectionSynonymy> values = sectionSynonymyDao.retrieveList();
            List<String> allSectionName = new ArrayList<>();
            for (SectionSynonymy value : values) {
                if (!allSectionName.contains(value.getSectionId())) {
                    allSectionName.add(value.getSectionId());
                }
            }
            // 获取所有已经存在的科室名称对应编号
            for (Section st : sts) {
                ksNameAndSectionId.put(st.getName(), st.getId());
            }
            InputStream inputStream = file.getInputStream();
            Workbook workbook = new XSSFWorkbook(inputStream);
            Sheet sheet = workbook.getSheetAt(0);
            for (Row row : sheet) {

                String ksName = getCellNum(row, 0);
                String ksStd = getCellNum(row, 1);
                String disable = getCellNum(row, 2);
                SectionSynonymy se = new SectionSynonymy();
                se.setDepartmentName(ksName);
                // 判断根据科室名称
                se.setModifierId(user.getUserId() + "");
                if (StringUtils.isNotBlank(disable)) {
                    se.setDisable(disable);
                } else {
                    se.setDisable("");
                }
                if (StringUtils.isNotBlank(ksStd)) {
                    addWarnBatch(ksStd, allSectionName);
                }
                if (StringUtils.isBlank(ksStd)) {
                    se.setSectionId("0");
                    addlist.add(se);
                } else if (ksNameAndSectionId.get(ksStd) != null) {
                    se.setSectionId(ksNameAndSectionId.get(ksStd) + "");
                    addlist.add(se);
                } else {
                    // 不存在需要新增
                    Section value = new Section();
                    value.setCnt(1);
                    value.setDisable(disable);
                    value.setModifierId(user.getUserId());
                    value.setName(ksStd);
                    value.setSexAgeFlag(0);
                    value.setSex(0);
                    value.setAge("");
                    Long sectionId = sectionDao.insert(value);
                    se.setSectionId(sectionId + "");
                    ksNameAndSectionId.put(ksStd, sectionId);
                    addlist.add(se);
                }
            }
            if (addlist.size() > 0) {
                // 删除之前的
                sectionSynonymyDao.deleteAll();
                sectionSynonymyDao.batchInsert(addlist);
                addlist.clear();
            }
            // 校验科室图片或科室大类是否都在同义词的标准词中
            // 校验黑名单科室是否都在同义词的标准科室名称
            checkData();
            // 删除已经没有对应的section。已经失效
            sectionDao.deleteSectionInvalid();
            return ReturnUtil.success();

        } else {
            ReturnCode rc = ReturnCode.DYNAMIC_DESC_EXCEPTION;
            rc.setDesc("文件有误");
            return ReturnUtil.fail(rc);
        }
    }

    private void checkData() {
        // 校验disable在同一个科室名称下是否有不同
        List<String> checkKsDisable = sectionSynonymyDao.checkKsNameDisable();
        StringBuffer errSynonymyList = new StringBuffer();
        if (checkKsDisable != null && checkKsDisable.size() > 0) {
            for (String value : checkKsDisable) {
                if (errSynonymyList.length() == 0) {
                    errSynonymyList.append("以下科室名称在同义词中的disable不一样:");
                }
                errSynonymyList.append(value + ";");
            }
        }
        // 校验二级科室必须在同义词中
        List<SectionImage> checkSection = sectionImageDao.checkKsNameSynonymy();
        StringBuffer errImageList = new StringBuffer();
        if (checkSection != null && checkSection.size() > 0) {
            for (SectionImage cs : checkSection) {
                if (errImageList.length() == 0) {
                    errImageList.append("以下图片不在科室同义词的科室名称中:");
                }
                errImageList.append(cs.getSectionId() + ";");
            }
        }
        if (errImageList.length() > 0 || errSynonymyList.length() > 0) {
            throw new RuntimeException(errImageList.toString() + "\n" + errSynonymyList.toString());
        }
    }

    public ReturnData sectionSynonymyAdd(String id, String sectionId, String departmentName, String disable,
                                         String changeFlag, User user) {
        List<Section> sts = sectionDao.retrieveList();
        Map<String, Long> ksNameAndSectionId = new HashMap<>();
        // 获取所有已经存在的科室名称对应编号
        for (Section st : sts) {
            ksNameAndSectionId.put(st.getName(), st.getId());
        }
        if (StringUtils.isNotBlank(sectionId)) {
            // 判断是否需要需要新增提示
            addWarn(sectionId);
        }
        // 新增
        if (StringUtils.isBlank(id)) {
            SectionSynonymy se = new SectionSynonymy();
            // 校验disable是否一致
            if (StringUtils.isNotBlank(sectionId)) {
                // 不需要新增section
                if (ksNameAndSectionId.get(sectionId) != null) {
                    se.setSectionId(ksNameAndSectionId.get(sectionId) + "");
                } else {
                    // 不存在需要新增
                    Section value = new Section();
                    value.setCnt(1);
                    value.setDisable(disable);
                    value.setModifierId(user.getUserId());
                    value.setName(sectionId);
                    value.setSexAgeFlag(0);
                    value.setSex(0);
                    value.setAge("");
                    Long section = sectionDao.insert(value);
                    se.setSectionId(section + "");
                }
            } else {
                se.setSectionId("0");
            }
            se.setDepartmentName(departmentName);
            se.setDisable(disable);
            se.setModifierId(user.getUserId() + "");
            sectionSynonymyDao.insert(se);
        } else {
            // 修改
            SectionSynonymy ss = sectionSynonymyDao.retrieveById(Long.parseLong(id));
            if (StringUtils.isBlank(sectionId)) {
                if (StringUtils.equals(changeFlag, "1")) {
                    Map<String, Object> param = new HashMap<>();
                    param.put("oldSectionId", ss.getSectionId());
                    param.put("newSectionId", "0");
                    param.put("disable", disable);
                    // 把所有相同的更新到新的
                    sectionSynonymyDao.updateAllBySectionName(param);
                } else {
                    Map<String, Object> param = new HashMap<>();
                    param.clear();
                    param.put("disable", disable);
                    param.put("id", id);
                    param.put("sectionId", "0");
                    param.put("modifierId", user.getUserId());
                    sectionSynonymyDao.updateSectionNameById(param);
                }
                // 判断修改后的科室名称是否在原来的科室名称中
            } else if (ksNameAndSectionId.get(sectionId) != null) {
                // 全部修改 只针对科室名称
                if (StringUtils.equals(changeFlag, "1")) {
                    Map<String, Object> param = new HashMap<>();
                    param.put("oldSectionId", ss.getSectionId());
                    param.put("newSectionId", ksNameAndSectionId.get(sectionId));
                    // 把所有相同的更新到新的
                    sectionSynonymyDao.updateAllBySectionName(param);
                } else {
                    // 只更新该条记录
                    Map<String, Object> param = new HashMap<>();
                    param.put("id", id);
                    param.put("sectionId", ksNameAndSectionId.get(sectionId));
                    param.put("modifierId", user.getUserId());
                    sectionSynonymyDao.updateSectionNameById(param);
                }
                // 更新后的再更新新的科室名称所有disable
                Map<String, Object> param = new HashMap<>();
                param.clear();
                param.put("oldSectionId", ksNameAndSectionId.get(sectionId));
                param.put("disable", disable);
                sectionSynonymyDao.updateAllBySectionName(param);
            } else {
                // 新增section
                // 不存在需要新增
                Section value = new Section();
                value.setCnt(1);
                value.setDisable(disable);
                value.setModifierId(user.getUserId());
                value.setName(sectionId);
                value.setSexAgeFlag(0);
                value.setSex(0);
                value.setAge("");
                Long section = sectionDao.insert(value);
                // 全部修改 只针对科室名称
                if (StringUtils.equals(changeFlag, "1")) {
                    Map<String, Object> param = new HashMap<>();
                    param.put("oldSectionId", ss.getSectionId());
                    param.put("newSectionId", section);
                    // 把所有相同的更新到新的
                    sectionSynonymyDao.updateAllBySectionName(param);
                } else {
                    // 只更新该条记录
                    Map<String, Object> param = new HashMap<>();
                    param.put("id", id);
                    param.put("sectionId", section);
                    param.put("modifierId", user.getUserId());
                    sectionSynonymyDao.updateSectionNameById(param);
                }
                // 更新所有的disable
                Map<String, Object> param = new HashMap<>();
                param.clear();
                param.put("oldSectionId", section);
                param.put("disable", disable);
                sectionSynonymyDao.updateAllBySectionName(param);
            }
            // 更新该记录的departmentName
            Map<String, Object> param = new HashMap<>();
            param.put("id", id);
            param.put("departmentName", departmentName);
            param.put("modifierId", user.getUserId());
            sectionSynonymyDao.updateSectionNameById(param);

        }
        // 校验国家对应科室是否在科室图片名称中
        checkData();
        // 如果失败,删除有可能添加的section的记录.并且维护好未校验的disable字段
        sectionDao.deleteSectionInvalid();
        return ReturnUtil.success();
    }

    private void addWarnBatch(String sectionId, List<String> allSectionName) {
        // 新增section需要新增提示
        if (StringUtils.isNotBlank(sectionId)) {
            if (!allSectionName.contains(sectionId)) {
                StaticData sd = new StaticData();
                sd.setCodeType("SECTION_ADD_WARN");
                sd.setDelFlag("0");
                sd.setRemarks("科室新增提示");
                sd.setValue(sectionId);
                staticDataDao.insert(sd);
                allSectionName.add(sectionId);
            }
        }
    }

    private void addWarn(String sectionId) {
        // 新增section需要新增提示
        if (StringUtils.isNotBlank(sectionId)) {
            Map<String, Object> param = new HashMap<>();
            param.put("sectionId", sectionId);
            List<SectionSynonymy> values = sectionSynonymyDao.retrieveList(param);
            if (values == null || values.size() == 0) {
                // 新增section需要新增提示
                //如果已经有该提示则不需要新增
                param.clear();
                param.put("code_type", "SECTION_ADD_WARN");
                param.put("value", sectionId);
                List<StaticData> value = staticDataDao.retrieveList(param);
                if (value == null || value.size() < 1) {
                    StaticData sd = new StaticData();
                    sd.setCodeType("SECTION_ADD_WARN");
                    sd.setDelFlag("0");
                    sd.setRemarks("科室新增提示");
                    sd.setValue(sectionId);
                    staticDataDao.insert(sd);
                }
            }
        }
    }
}
